#include <iostream>
using std::cout;
using std::endl;

class Data{
public:
    Data(){
        cout <<"Data()" << endl;
    }

    Data(int x)
    : _data(x)
    { cout << "Data(int)" << endl; }

    int getData() const{ return _data; }
    ~Data(){ cout << "~Data()" << endl; }
private:
    int _data = 10;
};

class MiddleLayer{
public:
    MiddleLayer(Data * p)
    : _pdata(p)
    { cout << "MiddleLayer(Data*)" << endl; }

    Data * operator->(){
        return _pdata;
    }

    Data & operator*(){
        return *_pdata;
    }
    ~MiddleLayer(){
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
        cout << "~MiddleLayer()" << endl;
    }
private:
    Data * _pdata;
};

class ThirdLayer{
public:
    ThirdLayer(MiddleLayer * pml)
    : _ml(pml)
    { cout << "ThirdLayer(Middlelayer*)" << endl; }

    MiddleLayer & operator->(){
        return *_ml;
    }

    MiddleLayer & operator*(){
        return *_ml;
    }
    ~ThirdLayer(){
        if(_ml){
            delete _ml;
            _ml = nullptr;
        }
        cout << "~ThirdLayer()" << endl;
    }
private:
    MiddleLayer * _ml;
};


void test0(){
    //ml是一个局部对象，当函数test0执行完时，一定会被销毁
    //执行析构函数就能够回收申请的空间(Data对象)
    //因此可以认为ml是一个智能指针的雏形
    //
    //智能指针的实现原理：通过对象的生命周期来管理资源
    //因为当对象被销毁时，一定会自动调用析构函数
    MiddleLayer ml(new Data);//Data * p = new Data
    //ml很像一个指针，但并不是指针，而是一个对象
    cout << ml->getData() << endl;
    //完整写法如下
    cout << (ml.operator->())->getData() << endl;

    cout << (*ml).getData() << endl;
    //完整写法如下
    cout << (ml.operator*()).getData() << endl;

    //原生的指针容易忘记回收，会发生内存泄漏
    Data * p = new Data;
    cout << p->getData() << endl;
    cout << (*p).getData() << endl;
    delete p;
}

void test1(){
    ThirdLayer t1(new MiddleLayer(new Data));
    t1->getData();
    //之所以能够这样写，是因为在MiddleLayer这一层已经重载了->运算符
    (t1.operator->())->getData();
    //完整调用流程
    ((t1.operator->()).operator->())->getData();
    (*(*t1)).getData();
}

int main(void){
    /* test0(); */
    test1();
    return 0;
}
